package com.xyh.cloudorder.utils;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

public class MyRSAUtils {
	public static final String KEY_ALGORITHM = "RSA";
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
    private static final String PUBLIC_KEY = "RSAPublicKey";
    private static final String PRIVATE_KEY = "RSAPrivateKey";
    
    
    public static Map<String, Object> initKey() throws Exception {
    	KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
    	keyPairGen.initialize(1024);
    	KeyPair keyPair = keyPairGen.generateKeyPair();
    	RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
    	RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
    	Map<String, Object> keyMap = new HashMap<String, Object>(2);
    	keyMap.put(PUBLIC_KEY, publicKey);
    	keyMap.put(PRIVATE_KEY, privateKey);
    	return keyMap;
    }
    
    public static byte[] decryptBASE64(String key) throws Exception {               
        return (new BASE64Decoder()).decodeBuffer(key);               
    }                                 
               
    public static String encryptBASE64(byte[] key) throws Exception {               
        return (new BASE64Encoder()).encodeBuffer(key);               
    }    
    public static String getPublicKey(Map<String, Object> keyMap) throws Exception {
        Key key = (Key) keyMap.get(PUBLIC_KEY); 
        byte[] publicKey = key.getEncoded(); 
        return encryptBASE64(key.getEncoded());
    }
    public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {
        Key key = (Key) keyMap.get(PRIVATE_KEY); 
        byte[] privateKey =key.getEncoded(); 
        return encryptBASE64(key.getEncoded());
    }  
    
    /**
	 * 拆分字符串
	 */
	public static String[] splitString(String string, int len) {
		int x = string.length() / len;
		int y = string.length() % len;
		int z = 0;
		if (y != 0) {
			z = 1;
		}
		String[] strings = new String[x + z];
		String str = "";
		for (int i = 0; i < x + z; i++) {
			if (i == x + z - 1 && y != 0) {
				str = string.substring(i * len, i * len + y);
			} else {
				str = string.substring(i * len, i * len + len);
			}
			strings[i] = str;
		}
		return strings;
	}
    
    
    
    /**
	 * BCD转字符串
	 */
	public static String bcd2Str(byte[] bytes) {
		char temp[] = new char[bytes.length * 2], val;

		for (int i = 0; i < bytes.length; i++) {
			val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
			temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');

			val = (char) (bytes[i] & 0x0f);
			temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
		}
		return new String(temp);
	}
    
    /**
	 * ASCII码转BCD码
	 * 
	 */
	public static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
		byte[] bcd = new byte[asc_len / 2];
		int j = 0;
		for (int i = 0; i < (asc_len + 1) / 2; i++) {
			bcd[i] = asc_to_bcd(ascii[j++]);
			bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));
		}
		return bcd;
	}
	
	public static byte asc_to_bcd(byte asc) {
		byte bcd;

		if ((asc >= '0') && (asc <= '9'))
			bcd = (byte) (asc - '0');
		else if ((asc >= 'A') && (asc <= 'F'))
			bcd = (byte) (asc - 'A' + 10);
		else if ((asc >= 'a') && (asc <= 'f'))
			bcd = (byte) (asc - 'a' + 10);
		else
			bcd = (byte) (asc - 48);
		return bcd;
	}
	
	public static byte[][] splitArray(byte[] data, int len) {
		int x = data.length / len;
		int y = data.length % len;
		int z = 0;
		if (y != 0) {
			z = 1;
		}
		byte[][] arrays = new byte[x + z][];
		byte[] arr;
		for (int i = 0; i < x + z; i++) {
			arr = new byte[len];
			if (i == x + z - 1 && y != 0) {
				System.arraycopy(data, i * len, arr, 0, y);
			} else {
				System.arraycopy(data, i * len, arr, 0, len);
			}
			arrays[i] = arr;
		}
		return arrays;
	}
    
	//根据私钥解密
    public static String decryptByPrivateKey(String data, PrivateKey privateKey) throws Exception {
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.DECRYPT_MODE, privateKey);
		// 模长
		int key_len = ((RSAKey) privateKey).getModulus().bitLength() / 8;
		byte[] bytes = data.getBytes();
		byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
		// 如果密文长度大于模长则要分组解密
		String ming = "";
		byte[][] arrays = splitArray(bcd, key_len);
		for (byte[] arr : arrays) {
			ming += new String(cipher.doFinal(arr));
		}
		return ming;
	}
    
    //根据公钥加密
    public static String encryptByPublicKey(String data, PublicKey publicKey) throws Exception {
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		// 模长
		int key_len = ((RSAKey) publicKey).getModulus().bitLength() / 8;
		// 加密数据长度 <= 模长-11
		String[] datas = splitString(data, key_len - 11);
		String mi = "";
		// 如果明文长度大于模长-11则要分组加密
		for (String s : datas) {
			mi += bcd2Str(cipher.doFinal(s.getBytes()));
		}
		return mi;
	}
	
    public static PublicKey getPublicKey(String key) throws Exception {
        byte[] keyBytes;
        keyBytes = (new BASE64Decoder()).decodeBuffer(key);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }
    
    public static PrivateKey getPrivateKey(String key) throws Exception {
        byte[] keyBytes;
        keyBytes = (new BASE64Decoder()).decodeBuffer(key);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }
    
    //根据私钥解密 参数都是String
    public static String decryptByPrivateKey_str(String data,String key) throws Exception{
    	return decryptByPrivateKey(data,getPrivateKey(key));
    }
    
    //根据公钥加密 参数都是String
    public static String encryptByPublicKey_str(String data,String key) throws Exception{
    	return encryptByPublicKey(data, getPublicKey(key));
    }
    
    public static void main(String[] args) {
    	Map<String, Object> keyMap;
    	try {
////	    	keyMap = initKey();
////	    	String publicKey = getPublicKey(keyMap);
////	    	System.out.println("String的公钥:" + publicKey);
////	    	String privateKey = getPrivateKey(keyMap);
////	    	System.out.println("String的私钥:" + privateKey);
//	    	
	    	String gongyao = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC/+AIvvY792Nml7eLApz3mhjlyoU5pkes64oBf6ByqJVf+aod8PeZhrKe+Yb8lpk8/TPc6prVgi1iQB4xW2oY8LI4zYf11qqMkh9SFkArTSK/ynBwBHbeONiam1tOO63FvFq3hj/+XX4T3u2dNM142mydT3627of6YdnFaKB5gxwIDAQAB";
//	    	String siyao = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAL/4Ai+9jv3Y2aXt4sCnPeaGOXKhTmmR6zrigF/oHKolV/5qh3w95mGsp75hvyWmTz9M9zqmtWCLWJAHjFbahjwsjjNh/XWqoySH1IWQCtNIr/KcHAEdt442JqbW047rcW8WreGP/5dfhPe7Z00zXjabJ1Pfrbuh/ph2cVooHmDHAgMBAAECgYBGS0yRqrn3njZkmi1UGmmCRlg273ZFFheq4lHbzKTicPY9xUiDaC86SPzLrANQiAuwxEAri+wSxDPT2c+75h0MvQJiTM+cPVm0RKqY9lzYlnsts/Wjx/dQCSr6TbsSnKbrO1xaO8t3ZlWK2EJ6OvwoLr3m5KVHRXOSNqsTeCnFEQJBAO6BzQW0nAR+gNjkWM+DnmReNZR/y4c14P/8tB5d2A982apj/ZX8QVCpT0eiP9AP+9Lm5XMIp8MQFjxgrPqrRZ0CQQDODGg/HtSEsLVdv7SVHP2DWow+2pMamhV+Et6CNhbewVv8Y/Htnts74uuz3h2mqAm5JUEaT5E/3pMviH40q0SzAkEAqJmpTPc3sxWaD7ib71Wjil/ukGMmhRZZT5xb13uPWKNxWzoD8Rq5MUP+fyz63yHtalE+serUbNfaYCQXI7wfIQJBAKmaauCyBupl7hQJ7aHj6AUMLm66SeXWuSQ6ce8qiK646Hea6RPX88uaoLtAdJWusbo1oR4AKqYxFmRE7OV7qKMCQQCnZVeHSk7V2roLxdxc8NhHugtIzFNpcnFDB2bPJ8NzJF++lxixL2Rp3a1pgzMzaEAFb4ueRSjS7wOJ5cRptLMZ";
//	    	//String mi = encryptByPublicKey("108lq", getPublicKey(gongyao));
	    	String mi = encryptByPublicKey_str("0101",gongyao);
	    	System.out.println("加密后的0101:" + mi);
	    	//9633A501D02CF5858B185F8F6E836D89F77FF1F8D778A172ACAF36D028C44E9F64849AB65F03264686240CD4FCB07618541DB22B834434CE73AFA0AADEDB33BF817E70C4C89B7EE5592E48707F276D3EA12D7A1EB0C07F6AEAB2CC7D706706CE33A77F4D7E400EBC13CFDE4D59AF09EE19F3CBA32DA203AC6F46501F5983FDB1
//	    	//私钥解密
//	    	//String mi2 = "6F5008F12CC97F9E66719D4D8D24B86BADC10E9B4A7343C370B1C4811B284A80C9ECAB5B4C9B57B79AB8DFF022118C41D6CBD615BC914CABE57B26F7ED050408E0AE3BE064122DDD7736DA97A9167A4566C0C84C6ECBEEE9CE0504F9CE58D42C36AB76A35A7907C4FF095248FF07CE407BEEB20D1DCAC132C951E23E0B10E89B";
//	    	//String ming = decryptByPrivateKey(mi,getPrivateKey(siyao));
//	    	String ming = decryptByPrivateKey_str(mi,siyao);
//	    	System.out.println("解密后的结果：" + ming);
    		
    		
    		//System.out.println(Long.parseLong(""));
	    	
	    	
    	} catch (Exception e) { 
    		e.printStackTrace();
    	}	 
	}
}
